#include "solid.h"
#include "mergesort.h"

Solid::Solid(unsigned int _id) : id(_id){
    color = Color(0.9, 0.9, 0.9);
    selected = false;
}

Solid::Solid(unsigned int _id, Color _c) : id(_id), color(_c){
    selected = false;
}

Solid::~Solid(){
    for(std::vector<Face *>::iterator itF = faces.begin(); itF != faces.end(); ++itF){
        delete (*itF);
    }
    for(std::vector<Edge *>::iterator itE = edges.begin(); itE != edges.end(); ++itE){
        delete (*itE);
    }
    for(std::vector<Vertex *>::iterator itV = vertices.begin(); itV != vertices.end(); ++itV){
        delete (*itV);
    }
}

void Solid::addFace(Face *_f){
    faces.push_back(_f);
}

void Solid::addEdge(Edge *_e){
    edges.push_back(_e);
}

void Solid::addVertix(Vertex *_v){
    vertices.push_back(_v);
}

void Solid::setColor(Color _c){
    color = _c;
}

unsigned int Solid::getID(){
    return id;
}

Face *Solid::getFace(int i){
    return faces.at(i);
}

Face *Solid::getLastFace(){
    return faces.at(faces.size() - 1);
}

Edge *Solid::getEdge(int i){
    return edges.at(i);
}

Vertex *Solid::getVertix(int i){
    return vertices.at(i);
}

Vertex *Solid::getLastVertix(){
    return vertices.at(vertices.size() - 1);
}

Vertex *Solid::getSecondLastVertix(){
    return vertices.at(vertices.size() - 2);
}

Color Solid::getColor(){
    return color;
}

void Solid::showAllVertices(){
    for(std::vector<Vertex*>::iterator itV = vertices.begin(); itV != vertices.end(); ++itV){
        (*itV)->getPoint().show();
    }
}

int Solid::sizeVertices(){
    return vertices.size();
}

int Solid::sizeEdges(){
    return edges.size();
}

int Solid::sizeFaces(){
    return faces.size();
}

Point Solid::getBoundingBoxCenter(){
    int n = vertices.size();
    Point p;
    double xPosition[n], yPosition[n], zPosition[n];
    for(int i = 0; i < n; i++){
        p = vertices.at(i)->getPoint();
        xPosition[i] = p.x;
        yPosition[i] = p.y;
        zPosition[i] = p.z;
    }

    MergeSort::sort(xPosition, 0, n);
    MergeSort::sort(yPosition, 0, n);
    MergeSort::sort(zPosition, 0, n);

    return Point(  (xPosition[0] + xPosition[n-1])/2.0, (yPosition[0] + yPosition[n-1])/2.0, (zPosition[0] + zPosition[n-1])/2.0  );
}

void Solid::scale(double _s){
    Point p = getBoundingBoxCenter(), v;

    int n = vertices.size();
    for(int i = 0; i < n; i++){
        v = vertices.at(i)->getPoint();
        v = v + ((v - p).normalization()*_s);
        vertices.at(i)->setPoint( v );
    }

//    Face *f;
//    n = faces.size();
//    for (int i = 0; i < n; i++){
//        f = faces.at(i);
//        if (f->isBezier()) f->resetBezier();
//    }
}

void Solid::translate(Point _t){
    Point v;

    int n = vertices.size();
    for(int i = 0; i < n; i++){
        v = vertices.at(i)->getPoint();
        v = v + _t;
        vertices.at(i)->setPoint( v );
    }

//    Face *f;
//    n = faces.size();
//    for (int i = 0; i < n; i++){
//        f = faces.at(i);
//        if (f->isBezier()) f->resetBezier();
//    }
}

double Solid::area(){
    double area = 0;

    for(std::vector<Face*>::iterator itF = faces.begin(); itF != faces.end(); ++itF){
        area += (*itF)->area();
    }

    return area;
}

void Solid::select(bool _s){
    selected = _s;
}

bool Solid::isSelected(){
    return selected;
}
